#ifndef RBT_PROFILE_OBJECT_INCLUDE
#define RBT_PROFILE_OBJECT_INCLUDE

#include "Text/Text.h"
#include <map>
#include <vector>

RETURNCODE E_OBJECT_UNINIT   = -701;
RETURNCODE E_KEYVALUE_UNINIT = -702;
RETURNCODE E_VALUEPARSE      = -703;
RETURNCODE E_CONVERT_VALUE   = -704;

enum OBJECT_TYPE
{
	OBJECT_INT32,
	OBJECT_UINT32,
	OBJECT_FLOAT64,
	OBJECT_INT64,
	OBJECT_UINT64,
	OBJECT_KEYVALUE,
	OBJECT_ARRAY,
	OBJECT_STRING,
	OBJECT_UNINIT,
};


class Object;
class KeyValue;
class Array;

class KeyValue
{
public:
	typedef std::map<string,Object> Values;
public:
	Values m_values;
public:
	typedef std::map<string,Object>::iterator iterator;

	iterator begin();
	iterator end();

	int32 Set( cstring& key , const Object& value );

	int32 Initialize( const KeyValue& values );
	int32 Initialize( const Values& values );

	int32 Uninitalize();
};



class Array
{
public:
	typedef std::vector< Object > Values;
public:
	Values m_values;
public:
	typedef Values::iterator iterator;

	iterator begin();
	iterator end();

	int32 Add( const Object& value );

	int32 Initalize( const Array& value );
	int32 Initalize( const Values& value );
	
	int32 Uninitalize();
};

const static KeyValue::Values rbtKeyValue;
const static Array::Values    rbtArray;
const static uint64           rbtValue[] = {0,0};

class Object
{
public:
	union ObjectValue
	{
		int32    vInt32;
		uint32    vUInt32;
		float64   vFloat64;
		int64    vInt64;
		uint64    vUInt64;
		KeyValue* vKeyValue;
		Array*    vArray;
		tchar*    vString;
	};

protected:
	ObjectValue m_value;
	OBJECT_TYPE m_type;
public:
	Object();

	Object& operator=( const Object& object );

	int32 Initalize( cint32& value );
	int32 Initalize( cuint32& value );
	int32 Initalize( cint64& value );
	int32 Initalize( cuint64& value );
	int32 Initalize( cfloat64& value );
	int32 Initalize( cstring& value );
	int32 Initalize( const KeyValue& value );
	int32 Initalize( const Array& value );

	int32 Uninitalize();

	OBJECT_TYPE GetType() { return m_type; }

	int32 GetValue(KeyValue*& keyValue)
	{
		if( m_type == OBJECT_KEYVALUE )
		{
			keyValue = m_value.vKeyValue;
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue( Array*& vArray )
	{
		if(m_type == OBJECT_ARRAY)
		{
			vArray = m_value.vArray;
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue( int32& value )
	{
		if(m_type == OBJECT_INT32)
		{
			value = m_value.vInt32;
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue( uint32& value )
	{
		if( (m_type == OBJECT_INT32  && m_value.vInt32 >= 0 ) ||
			 m_type == OBJECT_UINT32 )
		{
			value = m_value.vUInt32;
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue( int64& value )
	{
		if(m_type == OBJECT_UINT32)
		{
			value = static_cast<cint64>( m_value.vUInt32 );
			return R_SUCCEED;
		}
		if(m_type == OBJECT_INT32)
		{
			value = static_cast<cint64>( m_value.vInt32  );
			return R_SUCCEED;
		}
		if(m_type == OBJECT_INT64 )
		{
			value = m_value.vUInt64;
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue(uint64& value)
	{
		if( m_type == OBJECT_INT32 && m_value.vInt32 >= 0 )
		{
			value = static_cast<cuint64>(m_value.vUInt32);
			return R_SUCCEED;
		}
		if( m_type == OBJECT_INT64 && m_value.vUInt64 >=0 )
		{
			value = static_cast<cuint64>(m_value.vUInt64);
			return R_SUCCEED;
		}
		if(m_type == OBJECT_UINT32 || m_type == OBJECT_UINT64 )
		{
			value = static_cast<cuint64>(m_value.vUInt64);
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue( string& value )
	{
		if( m_type == OBJECT_STRING )
		{
			value = m_value.vString;
			return R_SUCCEED;
		}
		return E_CONVERT_VALUE;
	}

	int32 GetValue( float64& value )
	{
		if( m_type == OBJECT_FLOAT64 )
		{
			value = m_value.vFloat64;
			return R_SUCCEED;
		}
		return 0;
	}
};

typedef std::vector< Object > ObjectArray;
typedef std::map<string,Object> ObjectDirectory;

#endif